package com.example.springboot159.Interceptors;

import com.alibaba.fastjson.JSON;
import com.example.springboot159.annotation.XssRequired;
import com.example.springboot159.bean.BaseResult;
import com.example.springboot159.wrapper.RequestWrapper;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;

public class XssInterceptor extends HandlerInterceptorAdapter {
    private static final Logger logger = LoggerFactory.getLogger(XssInterceptor.class);
    private static final String XSS_VALID[] = {"<", ">", "(", ")", "\\", "svg", "alert", "confirm", "prompt", "onload", "onmouseover", "onfocus", "onerror", "xss"};

    /**
     * 在业务处理器处理请求之前被调用。预处理，可以进行编码、安全控制等处理；
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果方法不是@RequestMapping方法
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        XssRequired annotation = method.getAnnotation(XssRequired.class);//拿到方法的注解
        if (annotation != null) {
            Map<String, String[]> map = request.getParameterMap();
            if (map.isEmpty()) {
                RequestWrapper requestWrapper = new RequestWrapper(request);
                String body = requestWrapper.getBody();
                if (StringUtils.isNotBlank(body) && isContainXss(body)){
                    writeResponse(response);
                    return false;
                }
            } else {
                for (String key : map.keySet()) {
                    String[] value = map.get(key);
                    StringBuffer sb = new StringBuffer();
                    for (String v : value) {
                        if (StringUtils.isNotBlank(v)) {
                            sb.append(v);
                        }
                    }
                    if (isContainXss(sb.toString())) {
                        writeResponse(response);
                        return false;
                    }
                }
            }
        }
        return true;
    }

    public void writeResponse(HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write(JSON.toJSONString(BaseResult.buildResult("-9999", "参数错误,包含非法字符", null)));
        writer.flush();
        writer.close();
    }

    boolean isContainXss(String str) {
        if (StringUtils.isNotBlank(str)) {
            for (String xss : XSS_VALID) {
                if (str.contains(xss)) {
                    logger.info("xss 过滤 "+xss);
                    return true;
                }
            }
        }
        return  false;
    }
}
